package cn.echo.consul.manager.interceptor;

import cn.echo.consul.manager.encrypt.Md5;
import cn.echo.consul.manager.entity.UserPayload;
import cn.echo.consul.manager.exception.UnauthorizedException;
import cn.echo.consul.manager.service.AccessTokenService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static cn.echo.consul.manager.constant.HeaderFields.*;

@Slf4j
@RequiredArgsConstructor
@Order(-9999)
public class AuthenticationInterceptor extends HandlerInterceptorAdapter {

    final AccessTokenService accessTokenService;

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String token = request.getHeader(AUTH_TOKEN);
        UserPayload payload = accessTokenService.getPayload(token, UserPayload.class);
        if (payload == null) {
            throw new UnauthorizedException();
        }
        String ua = request.getHeader(UserAgent);
        String fingerprint = Md5.getMD5(ua);
        if (!fingerprint.equals(payload.getFingerprint())) {
            throw new UnauthorizedException();
        }

        request.setAttribute(AUTH_USER_ID, payload.getUserId());
        request.setAttribute(FINGERPRINT, fingerprint);
        request.setAttribute(CLIENT_IP, this.getClientIp(request));

        return true;
    }

    /**
     * 获取客户端IP
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值，第一个ip才是真实ip
            if (ip.contains(",")) {
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip.replaceAll(":", ".");
    }
}